The goal is to familiarize with the R package igraph.

Official website: http://igraph.org/r/

Be careful: igraph has also been developed in C and Python. If you do a search on the web you might arrive on http://igraph.org/c/ or http://igraph.org/python/ rather than http://igraph.org/r/

If you want to go further with igraph you can also have a look at that tutorial: http://kateto.net/networks-r-igraph

igraph package

Install the package igraph and load the library

install.packages("igraph")
library(igraph)
## 
## Attachement du package : 'igraph'
## Les objets suivants sont masqués depuis 'package:stats':
## 
##     decompose, spectrum
## L'objet suivant est masqué depuis 'package:base':
## 
##     union

1. Create a toy graph by hand

1.1. Giving the list of edges

There are 2 possible formats: either a vector that concatenates the indexes of linked nodes or a matrix with 2 rows.

EdgeList1 <- c(1,2, 1,3, 2,3, 3,5, 2,4, 4,5, 5,6, 4,6, 4,7, 6,7, 3,4)
EdgeList2 <- matrix(EdgeList1,nrow=2)
g1 <- graph(edges=EdgeList1, directed=FALSE)
g2 <- graph(edges=EdgeList2, directed=FALSE)
par(mfrow=c(1,2))
plot(g1)
plot(g2)

You obtain an object with class igraph:

class(g1)
## [1] "igraph"

You can specify the number of nodes \(n\) (in particular when there are isolated nodes):

g3 <- graph(edges=EdgeList1, n=9, directed=FALSE)
plot(g3)

Nodes are not necessarily of the numeric type:

EdgeListNames <- c("Eric", "Erwan", "Erwan","Ana")
g4 <- graph(edges=EdgeListNames)
plot(g4)

# Note that by default, the graph is directed 

With isolated nodes:

g5 <- graph(edges=EdgeListNames, isolates="Paul")
plot(g5)

It could be useful to start with a particular graph, specifying the number of node

g0 <- make_empty_graph(20)
gf <- make_full_graph(20)
gr <- make_ring(20)
gl <- make_lattice(c(4,6)) # here you input dimension
gs <- make_star(10)
par(mfrow=c(2,3))
plot(g0)
plot(gf)
plot(gr)
plot(gl)
plot(gs)

1.2. By reading a data.frame structure containing the list of edges:

Dataset (csv format) gathers friendship relationships among high-school students. It’s in the repo but you may also download it from: http://www.sociopatterns.org/datasets/high-school-contact-and-friendship-networks/

friends <- read.table(file='Friendship-network_data_2013.csv')
head(friends)
gfriends <- graph_from_data_frame(friends, directed=TRUE) 
gfriends
## IGRAPH 4c21001 DN-- 134 668 -- 
## + attr: name (v/c)
## + edges from 4c21001 (vertex names):
##  [1] 1 ->55  1 ->205 1 ->272 1 ->494 1 ->779 1 ->894 3 ->1   3 ->28  3 ->147
## [10] 3 ->272 3 ->407 3 ->674 3 ->884 27->63  27->173 28->202 28->327 28->353
## [19] 28->407 28->429 28->441 28->492 28->545 32->440 32->624 32->797 32->920
## [28] 34->151 34->277 34->502 34->866 45->48  45->79  45->335 45->496 45->601
## [37] 45->674 45->765 46->117 46->196 46->257 46->268 48->45  48->79  48->496
## [46] 55->1   55->170 55->205 55->252 55->272 55->779 55->883 55->894 61->797
## [55] 63->27  63->125 63->173 70->101 70->132 70->240 70->425 70->447 72->407
## [64] 72->674 72->857 79->45  79->48  79->335 79->496 79->601 79->674 79->765
## + ... omitted several edges
class(gfriends)
## [1] "igraph"
plot(gfriends)

You can also import other data.frame; try with a dataset containing information about media: the first file Dataset1-Media-Example-NODES.csv contains information about the nodes and the second one Dataset1-Media-Example-EDGES.csv contains the list of interactions (these are valued and of several different types):

nodes <- read.csv("Dataset1-Media-Example-NODES.csv", header=TRUE, as.is=TRUE)
head(nodes)
links <- read.csv("Dataset1-Media-Example-EDGES.csv", header=TRUE, as.is=TRUE)
head(links)
net <- graph_from_data_frame(d=links, vertices=nodes, directed=TRUE) 
class(net)
## [1] "igraph"
plot(net)

1.3. Using a file whose format is adapted to igraph:

Function read_graph is adapted to certain graph formats:

# usage: 
# This is not a command to be run !!!!
read_graph(file, format = c("edgelist", "pajek", "ncol", "lgl", "graphml", "dimacs", "graphdb", "gml", "dl"), ...)

The file lesmis.gml contains the weighted network of co-appearances of characters in Victor Hugo’s novel Les Miserables. Nodes represent characters as indicated by the labels and edges connect any pair of characters that appear in the same chapter of the book. The values on the edges are the number of such co-appearances. The file is in the repo or may be doawloaded from http://www-personal.umich.edu/~mejn/netdata/

miserab <- read_graph(file='lesmis.gml', format="gml") 
class(miserab)
## [1] "igraph"
plot(miserab)

1.4. Using an adjacency matrix

A <- matrix(c(0,0,0,0,0,0,1,1,0,1,0,1,0,1,1,0), 4, 4)
A
##      [,1] [,2] [,3] [,4]
## [1,]    0    0    0    0
## [2,]    0    0    1    1
## [3,]    0    1    0    1
## [4,]    0    1    1    0
plot(graph_from_adjacency_matrix(A, mode='undirected'))

1.5 By simulation

If you want to create toy graphs to play with, you can use the funtion sample_gnm specifying the number of nodes n and the number of edges m (the Erdös-Rényi model will be described soon).

set.seed(237)
toyG <- sample_gnm(n=50,m=12)
plot(toyG)

Note that you don’t visualize the 12 edges because they connect nodes that are close together.

2. Adjacency matrix and format conversions

You can convert a graph into its adjacency matrix:

Afriends <- as_adj(gfriends)
dim(Afriends)
## [1] 134 134

Beware: by default as_adj creates a matrix with sparse format and certain classical operations are. not possible :

is.matrix(Afriends)
## [1] FALSE
class(Afriends)
## [1] "dgCMatrix"
## attr(,"package")
## [1] "Matrix"
t(Afriends)
## Error in t.default(Afriends): l'argument n'est pas une matrice

To correct for that, just use option sparse=FALSE:

Afriends <- as_adj(gfriends, sparse=FALSE)
is.matrix(Afriends)
## [1] TRUE

3. Properties of a simple graph

Get familiar with the following functions by applying them to the graphs created above. Also use the package documentation (with help()) and READ it!

vcount()
ecount()
V()
E()
is.directed()

4. Elementary operations

You can do the fusion of 2 graphs by a simple + operation

E4 <- c(3,7, 2,5, 4,1, 6,5, 2,4)
g4 <- graph(edges=E4, directed=FALSE)
fused_G <- g1+g4
plot(fused_G)

Note that this produces (at least) 2 disconnected components and the nodes of the second graph have been renamed to be distinguished from the nodes of the first one. To connect these 2 graphs one needs to add edges

V(fused_G)
## + 14/14 vertices, from 06c7c6a:
##  [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14
G_more <- add.edges(fused_G,c(14,3, 11,5))
## Warning: `add.edges()` was deprecated in igraph 2.0.0.
## ℹ Please use `add_edges()` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
plot(G_more)

Another possibility is to use union, in which case the nodes that have the same names/numbers are considered the same:

fused_G2 <- union(g1,g4)
plot(fused_G2)

When the graph is bipartite, a vertex attribute is added to the vertices

Gb1 <- sample_bipartite(n1=5, n2=8, type="gnm", m=11)
vertex_attr(Gb1)
## $type
##  [1] FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
## [13]  TRUE
plot(Gb1,layout=layout_as_bipartite)

Gb2 <- sample_bipartite(n1=3, n2=4, type="gnm", m=7)
plot(Gb2,layout=layout_as_bipartite)

plot(Gb1+Gb2, layout=layout_as_bipartite)

# plot(union(Gb1,Gb2), layout=layout_as_bipartite) # This does'nt work ! 

It is not possible to simply do a union of 2 bipartites graphs. Indeed, the union function preserves vertices attributes. You could use the following code to correct for that:

union_bipartite<-function(list_nets){
    x<-do.call(igraph::union, list_nets)
    l<-length(list_nets)
    type_vec<-sapply(1:l,function(y) paste0("type_",y))
    or_types<-apply(sapply(1:l, function(k) vertex_attr(x, type_vec[k])),1,any)
    V(x)$type<-!(is.na(or_types)|!(or_types))
    x
}

net1<-sample_bipartite(15,10,"gnp",0.1)
V(net1)$name<-c(sapply(1:15,function(x) paste0("A_",x)),sapply(1:10,function(x) paste0("B_",x)))

net2<-sample_bipartite(15,10,"gnp",0.2)
V(net2)$name<-c(sapply(6:20,function(x) paste0("A_",x)),sapply(3:12,function(x) paste0("B_",x)))

net3<-sample_bipartite(20,12,"gnp",0.25)
V(net3)$name<-c(sapply(1:20,function(x) paste0("A_",x)),sapply(1:12,function(x) paste0("B_",x)))

nets<-union_bipartite(list(net1,net2,net3))
plot(net1,layout=layout_as_bipartite)

plot(net2,layout=layout_as_bipartite)

plot(nets,layout=layout_as_bipartite)

V(nets)[which(V(nets)$type)]$name
##  [1] "B_1"  "B_2"  "B_3"  "B_4"  "B_5"  "B_6"  "B_7"  "B_8"  "B_9"  "B_10"
## [11] "B_11" "B_12"
V(nets)[which(!V(nets)$type)]$name
##  [1] "A_1"  "A_2"  "A_3"  "A_4"  "A_5"  "A_6"  "A_7"  "A_8"  "A_9"  "A_10"
## [11] "A_11" "A_12" "A_13" "A_14" "A_15" "A_16" "A_17" "A_18" "A_19" "A_20"

5. Graphs visualisation

5.1 Network layouts: common algorithms for visualisation

To know more about that: https://igraph.org/r/doc/layout_.html

plot(gfriends)

To choose a specific layout, use the following option (use autocompletion to see the possible layouts):

plot(gfriends, layout=layout_as_star)

plot(gfriends, layout=layout_in_circle)

plot(gfriends, layout=layout_randomly)

Two popular visualization algorithms for having visualizations deemed “aesthetic”. If you want more information: https://halshs.archives-ouvertes.fr/halshs-00839905/document

plot(gfriends, layout=layout.fruchterman.reingold)

plot(gfriends, layout=layout.kamada.kawai)

5.2 Embellish your figures with igraph

To see all options of plot() just type ?igraph.plotting

The most common ones are:

  • vertex.color, vertex.shape, vertex.size, vertex.label color, shape, size and labels of the nodes
  • edge.color, edge.label edge color and labels
plot(net)

plot(net, edge.arrow.size=.4)

plot(net, vertex.color="orange", edge.color="blue", vertex.label.color="black", edge.arrow.size=.4)

If we want to use additional information to color the nodes according to the covariates (here the type of media, the size of the nodes according to the audience, the thickness of the edges according to their weight…) or on the edges (here valued and of different types). You can find this information here:

vertex_attr(net)
## $name
##  [1] "s01" "s02" "s03" "s04" "s05" "s06" "s07" "s08" "s09" "s10" "s11" "s12"
## [13] "s13" "s14" "s15" "s16" "s17"
## 
## $media
##  [1] "NY Times"            "Washington Post"     "Wall Street Journal"
##  [4] "USA Today"           "LA Times"            "New York Post"      
##  [7] "CNN"                 "MSNBC"               "FOX News"           
## [10] "ABC"                 "BBC"                 "Yahoo News"         
## [13] "Google News"         "Reuters.com"         "NYTimes.com"        
## [16] "WashingtonPost.com"  "AOL.com"            
## 
## $media.type
##  [1] 1 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3 3
## 
## $type.label
##  [1] "Newspaper" "Newspaper" "Newspaper" "Newspaper" "Newspaper" "Newspaper"
##  [7] "TV"        "TV"        "TV"        "TV"        "TV"        "Online"   
## [13] "Online"    "Online"    "Online"    "Online"    "Online"   
## 
## $audience.size
##  [1] 20 25 30 32 20 50 56 34 60 23 34 33 23 12 24 28 33
V(net)$media
##  [1] "NY Times"            "Washington Post"     "Wall Street Journal"
##  [4] "USA Today"           "LA Times"            "New York Post"      
##  [7] "CNN"                 "MSNBC"               "FOX News"           
## [10] "ABC"                 "BBC"                 "Yahoo News"         
## [13] "Google News"         "Reuters.com"         "NYTimes.com"        
## [16] "WashingtonPost.com"  "AOL.com"
edge_attr(net)
## $weight
##  [1] 10 12 22 21 22 21 21 11 12 22 23 20 11 11 21 23 21 21 21 22 21 21 21 23 21
## [26] 22 22 21 21  2  5  1  1  2  2  3  1  1  1  1  2  2  4  2  4  4  4  1  1  1
## [51]  1  1
## 
## $type
##  [1] "hyperlink" "hyperlink" "hyperlink" "hyperlink" "mention"   "mention"  
##  [7] "mention"   "mention"   "mention"   "hyperlink" "hyperlink" "mention"  
## [13] "hyperlink" "hyperlink" "mention"   "hyperlink" "hyperlink" "mention"  
## [19] "mention"   "mention"   "hyperlink" "hyperlink" "hyperlink" "hyperlink"
## [25] "hyperlink" "hyperlink" "mention"   "mention"   "hyperlink" "hyperlink"
## [31] "hyperlink" "hyperlink" "mention"   "hyperlink" "mention"   "hyperlink"
## [37] "mention"   "hyperlink" "mention"   "hyperlink" "mention"   "mention"  
## [43] "hyperlink" "hyperlink" "hyperlink" "mention"   "hyperlink" "hyperlink"
## [49] "mention"   "hyperlink" "hyperlink" "mention"
E(net)$weight
##  [1] 10 12 22 21 22 21 21 11 12 22 23 20 11 11 21 23 21 21 21 22 21 21 21 23 21
## [26] 22 22 21 21  2  5  1  1  2  2  3  1  1  1  1  2  2  4  2  4  4  4  1  1  1
## [51]  1  1
plot(net, vertex.label=V(net)$media, edge.arrow.size=.4)

plot(net, vertex.label=V(net)$media, edge.arrow.size=.4, vertex.color=V(net)$media.type)

plot(net, vertex.label=V(net)$media, edge.arrow.size=.4, vertex.color=V(net)$media.type, vertex.size=V(net)$audience.size)

plot(net, vertex.label=V(net)$media, vertex.color=V(net)$media.type, vertex.size=V(net)$audience.size, edge.width=E(net)$weight)

To change the color of the link based on its type

E(net)$color[E(net)$type=="hyperlink"]<-"blue"
E(net)$color[E(net)$type=="mention"]<-"red"
plot(net, edge.arrow.size=.4)

Exercise 1

Search the web for graphs and import them onto your machine (you will keep the data recovery address as a comment in your file). Vary the original formats if you can, and the type of graph (directed or not). Determine the order (number of nodes) and size (number of edges) of the graphs and visualize them.

Here is a list of servers offering real graph data:

or load data from the igraphdata package.

6. Properties of a simple graph

Let us recall the following functions to determine the order and size of a graph, obtain the list of nodes or edges as well as know if the graph is directed or not:

vcount(miserab)
## [1] 77
ecount(miserab)
## [1] 254
V(miserab)
## + 77/77 vertices, from 328e1d0:
##  [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
## [26] 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
## [51] 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
## [76] 76 77
E(miserab)
## + 254/254 edges from 328e1d0:
##   [1]  1-- 2  1-- 3  1-- 4  3-- 4  1-- 5  1-- 6  1-- 7  1-- 8  1-- 9  1--10
##  [11] 11--12  4--12  3--12  1--12 12--13 12--14 12--15 12--16 17--18 17--19
##  [21] 18--19 17--20 18--20 19--20 17--21 18--21 19--21 20--21 17--22 18--22
##  [31] 19--22 20--22 21--22 17--23 18--23 19--23 20--23 21--23 22--23 17--24
##  [41] 18--24 19--24 20--24 21--24 22--24 23--24 13--24 12--24 24--25 12--25
##  [51] 25--26 24--26 12--26 25--27 12--27 17--27 26--27 12--28 24--28 26--28
##  [61] 25--28 27--28 12--29 28--29 24--30 28--30 12--30 24--31 31--32 12--32
##  [71] 24--32 28--32 12--33 12--34 28--34 12--35 30--35 12--36 35--36 30--36
##  [81] 35--37 36--37 12--37 30--37 35--38 36--38 37--38 12--38 30--38 35--39
##  [91] 36--39 37--39 38--39 12--39 30--39 26--40 26--41 25--42 26--42 42--43
## + ... omitted several edges
is.directed(miserab)
## Warning: `is.directed()` was deprecated in igraph 2.0.0.
## ℹ Please use `is_directed()` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## [1] FALSE

and for the graph gfriends:

vcount(gfriends)
## [1] 134
ecount(gfriends)
## [1] 668
V(gfriends)
## + 134/134 vertices, named, from 4c21001:
##   [1] 1    3    27   28   32   34   45   46   48   55   61   63   70   72   79  
##  [16] 80   85   92   101  117  119  120  122  124  125  132  134  147  151  156 
##  [31] 159  165  170  173  184  190  196  200  201  202  205  211  213  214  219 
##  [46] 222  232  240  242  245  248  252  255  257  265  268  272  275  277  285 
##  [61] 312  325  327  335  343  353  364  366  388  407  425  429  440  441  447 
##  [76] 452  465  468  471  480  486  488  491  492  494  496  498  502  520  531 
##  [91] 545  564  576  577  587  601  603  605  612  622  624  634  642  674  691 
## [106] 694  753  765  769  771  779  797  798  845  857  866  867  869  883  884 
## [121] 894  920  959  960  970  974  1228 1332 1401 1485 1519 1594 1828 38
E(gfriends)
## + 668/668 edges from 4c21001 (vertex names):
##  [1] 1 ->55  1 ->205 1 ->272 1 ->494 1 ->779 1 ->894 3 ->1   3 ->28  3 ->147
## [10] 3 ->272 3 ->407 3 ->674 3 ->884 27->63  27->173 28->202 28->327 28->353
## [19] 28->407 28->429 28->441 28->492 28->545 32->440 32->624 32->797 32->920
## [28] 34->151 34->277 34->502 34->866 45->48  45->79  45->335 45->496 45->601
## [37] 45->674 45->765 46->117 46->196 46->257 46->268 48->45  48->79  48->496
## [46] 55->1   55->170 55->205 55->252 55->272 55->779 55->883 55->894 61->797
## [55] 63->27  63->125 63->173 70->101 70->132 70->240 70->425 70->447 72->407
## [64] 72->674 72->857 79->45  79->48  79->335 79->496 79->601 79->674 79->765
## [73] 80->120 80->285 80->468 80->601 85->190 85->213 85->214 85->335 85->603
## [82] 85->605 85->765 92->468 92->845
## + ... omitted several edges
is.directed(gfriends)
## [1] TRUE

7. Degree distribution with igraph

When the graph is undirected:

degree(miserab)
##  [1] 10  1  3  3  1  1  1  1  1  1  1 36  2  1  1  1  9  7  7  7  7  7  7 15 11
## [26] 16 11 17  4  8  2  4  1  2  6  6  6  6  6  3  1 11  3  3  2  1  1  2 22  7
## [51]  2  7  2  1  4 19  2 11 15 11  9 11 13 12 13 12 10  1 10 10 10  9  3  2  2
## [76]  7  7

and when its directed, indegrees and outdegrees are obtained with

degree(gfriends, mode="in")
##    1    3   27   28   32   34   45   46   48   55   61   63   70   72   79   80 
##   11    4    3   10    2    4    8    5    5    9    0    2    5    4    8    5 
##   85   92  101  117  119  120  122  124  125  132  134  147  151  156  159  165 
##    5    3    8   11    8    4    6    2    7    6    4    3    5    0    0    1 
##  170  173  184  190  196  200  201  202  205  211  213  214  219  222  232  240 
##    8    2    5    4    6    4    4    3   11    3    3    5    4    3    2    6 
##  242  245  248  252  255  257  265  268  272  275  277  285  312  325  327  335 
##    3    9    2    7    2    4    7    5   15    3    3    4    2    6    6    6 
##  343  353  364  366  388  407  425  429  440  441  447  452  465  468  471  480 
##    4    6    6    1    5   12    8    5    3    8    9    8    4    6    2    2 
##  486  488  491  492  494  496  498  502  520  531  545  564  576  577  587  601 
##    2    3    4    6    8    7    2    6    3    3    3    3    3    2    7    4 
##  603  605  612  622  624  634  642  674  691  694  753  765  769  771  779  797 
##    5    7    2    7    7    9    8    6   13    5    4    6    4    1    9   10 
##  798  845  857  866  867  869  883  884  894  920  959  960  970  974 1228 1332 
##    4    5    3    5    2   10   12    3    9    2    5    5    2    2    2    7 
## 1401 1485 1519 1594 1828   38 
##    4    1    5    2    2    3
degree(gfriends, mode="out")
##    1    3   27   28   32   34   45   46   48   55   61   63   70   72   79   80 
##    6    7    2    8    4    4    7    4    3    8    1    3    5    3    7    4 
##   85   92  101  117  119  120  122  124  125  132  134  147  151  156  159  165 
##    7    2    9   16    6    3    5    2    9    7    3   10   13    1    2    1 
##  170  173  184  190  196  200  201  202  205  211  213  214  219  222  232  240 
##    6    3    3    4    5    2    8    5   12    3    2    3    1    3    2    7 
##  242  245  248  252  255  257  265  268  272  275  277  285  312  325  327  335 
##    3    7    3    7    1    3    9    5   11    3    6    5    2    7    8    3 
##  343  353  364  366  388  407  425  429  440  441  447  452  465  468  471  480 
##    3    5    5    1    8   13   10    7    5    7    8    5    3    7    2    2 
##  486  488  491  492  494  496  498  502  520  531  545  564  576  577  587  601 
##    2    3    4    9    8    8    2    5    4    3    3    2    4    2    5    7 
##  603  605  612  622  624  634  642  674  691  694  753  765  769  771  779  797 
##    6    5    2    8   10    3    7    6   10    2    2    3    9    2    9    5 
##  798  845  857  866  867  869  883  884  894  920  959  960  970  974 1228 1332 
##    2    6    5    9    2    4   13    2   11    3    6    2    2    2    3    6 
## 1401 1485 1519 1594 1828   38 
##    4    1    6    2    2    0

Empirical distribution of degrees:

degree_distribution(miserab)
##  [1] 0.00000000 0.22077922 0.12987013 0.07792208 0.03896104 0.00000000
##  [7] 0.06493506 0.12987013 0.01298701 0.03896104 0.06493506 0.07792208
## [13] 0.02597403 0.02597403 0.00000000 0.02597403 0.01298701 0.01298701
## [19] 0.00000000 0.01298701 0.00000000 0.00000000 0.01298701 0.00000000
## [25] 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000
## [31] 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000
## [37] 0.01298701
degree_distribution(gfriends, mode="out") 
##  [1] 0.007462687 0.052238806 0.194029851 0.179104478 0.074626866 0.111940299
##  [7] 0.074626866 0.104477612 0.067164179 0.052238806 0.029850746 0.014925373
## [13] 0.007462687 0.022388060 0.000000000 0.000000000 0.007462687

Graphical representation of this degree empirical distribution:

barplot(degree_distribution(miserab), names.arg=as.character(0:max(degree(miserab))), col='green', main='Degrees for the graph Les Misérables')

Degrees via the adjacency matrix

We can check by hand that the degrees of the nodes are indeed given by the sum of the row or column of the adjacency matrix:

Afriends <- as_adj(gfriends)
sum(Afriends[1,])
## [1] 6
# rowSums(Afriends) # be careful, that doesn't work because it's not a matrix! 
rowSums(as.matrix(Afriends)) # Pay attention to the format of this output!
##    1    3   27   28   32   34   45   46   48   55   61   63   70   72   79   80 
##    6    7    2    8    4    4    7    4    3    8    1    3    5    3    7    4 
##   85   92  101  117  119  120  122  124  125  132  134  147  151  156  159  165 
##    7    2    9   16    6    3    5    2    9    7    3   10   13    1    2    1 
##  170  173  184  190  196  200  201  202  205  211  213  214  219  222  232  240 
##    6    3    3    4    5    2    8    5   12    3    2    3    1    3    2    7 
##  242  245  248  252  255  257  265  268  272  275  277  285  312  325  327  335 
##    3    7    3    7    1    3    9    5   11    3    6    5    2    7    8    3 
##  343  353  364  366  388  407  425  429  440  441  447  452  465  468  471  480 
##    3    5    5    1    8   13   10    7    5    7    8    5    3    7    2    2 
##  486  488  491  492  494  496  498  502  520  531  545  564  576  577  587  601 
##    2    3    4    9    8    8    2    5    4    3    3    2    4    2    5    7 
##  603  605  612  622  624  634  642  674  691  694  753  765  769  771  779  797 
##    6    5    2    8   10    3    7    6   10    2    2    3    9    2    9    5 
##  798  845  857  866  867  869  883  884  894  920  959  960  970  974 1228 1332 
##    2    6    5    9    2    4   13    2   11    3    6    2    2    2    3    6 
## 1401 1485 1519 1594 1828   38 
##    4    1    6    2    2    0
degree(gfriends, mode="out") # idem 
##    1    3   27   28   32   34   45   46   48   55   61   63   70   72   79   80 
##    6    7    2    8    4    4    7    4    3    8    1    3    5    3    7    4 
##   85   92  101  117  119  120  122  124  125  132  134  147  151  156  159  165 
##    7    2    9   16    6    3    5    2    9    7    3   10   13    1    2    1 
##  170  173  184  190  196  200  201  202  205  211  213  214  219  222  232  240 
##    6    3    3    4    5    2    8    5   12    3    2    3    1    3    2    7 
##  242  245  248  252  255  257  265  268  272  275  277  285  312  325  327  335 
##    3    7    3    7    1    3    9    5   11    3    6    5    2    7    8    3 
##  343  353  364  366  388  407  425  429  440  441  447  452  465  468  471  480 
##    3    5    5    1    8   13   10    7    5    7    8    5    3    7    2    2 
##  486  488  491  492  494  496  498  502  520  531  545  564  576  577  587  601 
##    2    3    4    9    8    8    2    5    4    3    3    2    4    2    5    7 
##  603  605  612  622  624  634  642  674  691  694  753  765  769  771  779  797 
##    6    5    2    8   10    3    7    6   10    2    2    3    9    2    9    5 
##  798  845  857  866  867  869  883  884  894  920  959  960  970  974 1228 1332 
##    2    6    5    9    2    4   13    2   11    3    6    2    2    2    3    6 
## 1401 1485 1519 1594 1828   38 
##    4    1    6    2    2    0
sum(Afriends[,1])
## [1] 11
colSums(as.matrix(Afriends)) # Pay attention to the format of this output!
##    1    3   27   28   32   34   45   46   48   55   61   63   70   72   79   80 
##   11    4    3   10    2    4    8    5    5    9    0    2    5    4    8    5 
##   85   92  101  117  119  120  122  124  125  132  134  147  151  156  159  165 
##    5    3    8   11    8    4    6    2    7    6    4    3    5    0    0    1 
##  170  173  184  190  196  200  201  202  205  211  213  214  219  222  232  240 
##    8    2    5    4    6    4    4    3   11    3    3    5    4    3    2    6 
##  242  245  248  252  255  257  265  268  272  275  277  285  312  325  327  335 
##    3    9    2    7    2    4    7    5   15    3    3    4    2    6    6    6 
##  343  353  364  366  388  407  425  429  440  441  447  452  465  468  471  480 
##    4    6    6    1    5   12    8    5    3    8    9    8    4    6    2    2 
##  486  488  491  492  494  496  498  502  520  531  545  564  576  577  587  601 
##    2    3    4    6    8    7    2    6    3    3    3    3    3    2    7    4 
##  603  605  612  622  624  634  642  674  691  694  753  765  769  771  779  797 
##    5    7    2    7    7    9    8    6   13    5    4    6    4    1    9   10 
##  798  845  857  866  867  869  883  884  894  920  959  960  970  974 1228 1332 
##    4    5    3    5    2   10   12    3    9    2    5    5    2    2    2    7 
## 1401 1485 1519 1594 1828   38 
##    4    1    5    2    2    3
degree(gfriends, mode="in") # idem 
##    1    3   27   28   32   34   45   46   48   55   61   63   70   72   79   80 
##   11    4    3   10    2    4    8    5    5    9    0    2    5    4    8    5 
##   85   92  101  117  119  120  122  124  125  132  134  147  151  156  159  165 
##    5    3    8   11    8    4    6    2    7    6    4    3    5    0    0    1 
##  170  173  184  190  196  200  201  202  205  211  213  214  219  222  232  240 
##    8    2    5    4    6    4    4    3   11    3    3    5    4    3    2    6 
##  242  245  248  252  255  257  265  268  272  275  277  285  312  325  327  335 
##    3    9    2    7    2    4    7    5   15    3    3    4    2    6    6    6 
##  343  353  364  366  388  407  425  429  440  441  447  452  465  468  471  480 
##    4    6    6    1    5   12    8    5    3    8    9    8    4    6    2    2 
##  486  488  491  492  494  496  498  502  520  531  545  564  576  577  587  601 
##    2    3    4    6    8    7    2    6    3    3    3    3    3    2    7    4 
##  603  605  612  622  624  634  642  674  691  694  753  765  769  771  779  797 
##    5    7    2    7    7    9    8    6   13    5    4    6    4    1    9   10 
##  798  845  857  866  867  869  883  884  894  920  959  960  970  974 1228 1332 
##    4    5    3    5    2   10   12    3    9    2    5    5    2    2    2    7 
## 1401 1485 1519 1594 1828   38 
##    4    1    5    2    2    3

8. Other statistics

Get familiar with the following igraph functions for a graph \(G\), and apply them to Les Misérables and gfriends graphs:

components(G)                      
edge_density(G)
diameter(G, directed=TRUE, unconnected=FALSE)
diameter(G, directed=TRUE, unconnected=TRUE)
get_diameter(G, directed=TRUE)
count_triangles(G) 
transitivity(G)

neighbors(G, 1,  mode='out')
neighbors(G, 1, mode='in')
neighbors(G, 1, mode='all')
 
K3 <- cliques(G, min=3, max=3)
K3[[1]] 
length(K3) 
sum(count_triangles(G))/3

closeness(G,mode="total") 
closeness(G)
betweenness(G)
plot(G, vertex.size=betweenness(G))

Exercise 2.

  • Analyze the graphs from exercise 1 (previous session) with the descriptive statistics you know.
  • Make sure you understand what formulas are used by each of the functions above. Do they correspond to the definitions seen in class? Pay particular attention to the cases of directed graphs and the connectivity problem.
  • Some statistics only make sense for related graphs. In this case, select the largest connected component of the graph and apply the statistical calculation on this component.
  • Do the same on the famous Karate Club graph (available in R): In 1977, W. W. Zachary recorded interactions in a karate club for two years. During observation, a conflict developed between the administrator and the instructor.
library(igraphdata)
data(karate)